<?php
namespace App\Plugins;

use App\Helpers\Utils,
	\Phalcon\Db\Adapter\Pdo,
	\Phalcon\Db\Profiler,
	App\Libraries\Log\Logger;

/**
 * 数据库监听插件
 * @package App\Plugins
 */
class DbListenerPlugin {

	#region 属性

	/**
	 * 数据库的操作性能分析数组
	 * @var \Phalcon\Db\Profiler
	 */
	protected $profiler;

	/**
	 * Phalcon\Di 对象
	 * @var \Phalcon\Di
	 */
	protected $di;

	/**
	 * 日志帮助类对象
	 * @var \App\Helpers\LoggerHelper
	 */
	protected $log;

	/**
	 * 相关配置
	 * @var \Phalcon\Config
	 */
	private $config;

	#endregion

	function __construct() {
		$this->di = \Phalcon\Di::getDefault();
		$this->config = Utils::configItem("app");

		//根据配置判断是否要进行验签
		if (isset($this->config->enableSqlLog) && $this->config->enableSqlLog) {
			$this->log = new Logger(Utils::configItem("log"), "sql");
		}
		//根据配置判断是否要进行性能分析
		if (isset($this->config->enableDbProfiler) && $this->config->enableDbProfiler) {
			$this->profiler = new Profiler();
		}
	}

	/**
	 * 在发送SQL到数据库前触发
	 * @param $event
	 * @param Pdo $connection
	 * @return bool
	 */
	function beforeQuery($event, Pdo $connection) {
		// SQL 语句
		$sql = $connection->getSQLStatement();

		// 检查是否有恶意关键词，DROP/ALTER 操作是不允许的, 这肯定是一个注入!
		if (preg_match('/DROP|ALTER/i', $sql)) {
			// 返回false中断此操作
			return false;
		}

		// 开始SQL语句的性能分析
		if (isset($this->profiler)) {
			$this->profiler->startProfile($connection->getSQLStatement(), $connection->getSqlVariables());
		} elseif (isset($this->logger)) {
			// 记录SQL
			$this->_writeSqlStatement($sql);
		}

		// 一切正常
		return true;
	}

	/**
	 * 在发送SQL到数据库执行后触发
	 * @param $event
	 * @param Pdo $connection
	 */
	function afterQuery($event, Pdo $connection) {
		// 结束SQL语句的性能分析
		if (isset($this->profiler)) {
			$this->profiler->stopProfile();
			$this->_writeProfiling();
		}
	}

	/**
	 * 将性能分析信息写入日志
	 */
	private function _writeProfiling() {

		if (isset($this->profiler)) {
			//获得最后执行的性能分析描述
			$profile = $this->profiler->getLastProfile();
			$params = $profile->getSqlVariables();

			$this->log->begin();
			$this->log->info("SQL语句: {$profile->getSQLStatement()}");
			if ($params)
				$this->log->info("绑定参数:" . json_encode($params));

			$this->log->info("执行时间: " . Utils::microTimeFormat("Y-m-d H:i:s.x", $profile->getInitialTime()) . " - " . Utils::microTimeFormat("Y-m-d H:i:s.x", $profile->getFinalTime()));
			$this->log->info("执行时间（毫秒数）: " . $profile->getTotalElapsedSeconds());
			$this->log->commit();

		}
	}

	/**
	 * 记录执行的SQL
	 */
	private function _writeSqlStatement($sql) {
		$this->log->info("SQL语句: {$sql}");
	}
}